package com.googlecode.perfectable.visuable.screen;

import java.io.Writer;

import javax.xml.stream.XMLOutputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamWriter;

import com.googlecode.perfectable.visuable.parse.DocumentConstants;
import com.googlecode.perfectable.visuable.renderer.VisualRenderer;
import com.googlecode.perfectable.visuable.renderer.xml.XmlElementRenderer;
import com.googlecode.perfectable.visuable.renderer.xml.XmlVisualRenderer;
import com.googlecode.perfectable.visuable.visual.Visual;

public class StandardScreen implements Screen {
	private static final XMLOutputFactory XML_WRITER_FACTORY = XMLOutputFactory.newInstance();

	private static final String XHTML_DTD =
			"<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\"\n \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n";

	private final Visual root;

	public StandardScreen(Visual root) {
		this.root = root;
	}

	@Override
	public void write(Writer writer) {
		try {
			XMLStreamWriter xmlWriter = XML_WRITER_FACTORY.createXMLStreamWriter(writer);
			xmlWriter.setDefaultNamespace(DocumentConstants.XHTML_NAMESPACE);
			xmlWriter.setNamespaceContext(DocumentConstants.NAMESPACE_CONTEXT);
			xmlWriter.writeDTD(XHTML_DTD);
			xmlWriter.writeStartDocument();
			try(VisualRenderer painter = new NamespacedXmlVisualRenderer(xmlWriter)) {
				this.root.render(painter);
			}
			xmlWriter.writeEndDocument();
			xmlWriter.flush();
			xmlWriter.close();
		}
		catch(XMLStreamException e) {
			throw new RuntimeException(e); // TODO Auto-generated catch block
		}
	}

	private static class NamespacedXmlVisualRenderer extends XmlVisualRenderer {
		public NamespacedXmlVisualRenderer(XMLStreamWriter xmlWriter) {
			super(xmlWriter);
		}

		@Override
		protected XmlElementRenderer createElementRenderer(XMLStreamWriter xmlWriter, String elementName) {
			return new NamespacedXmlElementRenderer(xmlWriter, elementName);
		}
	}

	private static class NamespacedXmlElementRenderer extends XmlElementRenderer {
		public NamespacedXmlElementRenderer(XMLStreamWriter xmlWriter, String elementName) {
			super(xmlWriter, elementName);
			try {
				xmlWriter.writeDefaultNamespace(DocumentConstants.XHTML_NAMESPACE);
			}
			catch(XMLStreamException e) {
				throw new RuntimeException(e); // TODO Auto-generated catch block
			}
		}
	}

}
